#include <graphics.h>
#include <conio.h>
#include <time.h>
#include <stdio.h>
#pragma comment(lib,"Winmm.lib")

#define Max 100		//蛇的最大节数

#define	up 119
#define	down 115
#define left 97
#define	right 100

enum positon { sright = 100, sleft = 97, sup = 119, sdown = 115, paus = 112 };

typedef struct pointxy
{
	int x;
	int y;
}pointxy;

//蛇
struct Snake
{
	int lenth;			//蛇的节数
	pointxy xy[Max];	//蛇最大长度
	char position;		//标记方向
	int speed;          //蛇的速度
}snake;


//食物
struct Food
{
	pointxy foodxy;		//食物坐标
	int symbol;		//食物存在标志
	int grade;			//分数
}Food;


/*所用函数声明*/

void gotoxy();
void CreateMap();			//初始化地图
void createsnake();			//初始化蛇
void drawsnake();			//蛇的绘制
void SnakeMove();			//蛇的移动
void speedup();				//加速
void speedup2();             //地域模式的加速
void CreateFood();			//初始化食物
void drawfood();			//绘制食物
void gameover();			//停止游戏(撞墙结束)
void gameover2();			//停止游戏（碰到自己）
void topic();				//生成封面
void grade();				//显示分数
void GameEnd();				//游戏结束界面
void HitWall();				//判断是否撞墙
void EatFood();				//吃食物
void again();				//重新开始游戏
void difficult();           //困难模式

void gotoxy(int x, int y) {
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
	COORD pos;
	pos.X = x;
	pos.Y = y;
	SetConsoleCursorPosition(handle, pos);
}

int main()
{
	initgraph(480, 320);
	topic();				//显示封面
	initgraph(800, 700);

	setbkcolor(BLACK);
	cleardevice();
	createsnake();
	while (1)
	{
		gotoxy(0, 0);
		settextcolor(COLORREF RGB(134, 235, 246));
		cleardevice();		//刷新蛇的路径
		CreateMap();
		grade();
		drawsnake();
		speedup();
		drawfood();
		SnakeMove();
		if (Food.symbol == 0)
		{
			CreateFood();
		}
		Sleep(snake.speed);
		HitWall();
		EatFood();
	}

	_getch();
	closegraph();
	return 0;

}

//绘制地图
void CreateMap()
{
	setlinecolor(COLORREF RGB(11, 191, 206));
	rectangle(90, 90, 510, 610);
	rectangle(100, 100, 500, 600);
}

//初始化蛇
void createsnake()
{
	snake.xy[3].x = 100;
	snake.xy[3].y = 100;

	snake.xy[2].x = 110;
	snake.xy[2].y = 100;

	snake.xy[1].x = 120;
	snake.xy[1].y = 100;

	snake.xy[0].x = 130;
	snake.xy[0].y = 100;

	snake.lenth = 4;
	snake.position = sright;

	Food.symbol = 0;

}

//蛇的绘制
void drawsnake()
{
	gotoxy(0, 0);
	int i;
	setlinecolor(LIGHTMAGENTA);
	fillrectangle(snake.xy[0].x, snake.xy[0].y, snake.xy[0].x + 10, snake.xy[0].y + 10);
	for (i = 1; i < snake.lenth; i++)
	{
		setlinecolor(BLUE);
		fillrectangle(snake.xy[i].x, snake.xy[i].y, snake.xy[i].x + 10, snake.xy[i].y + 10);
	}

}

//蛇的运动
void SnakeMove()
{
	int i, j;
	//除了第一节以外,后一节蛇身的坐标是前一节的坐标
	for (i = snake.lenth - 1; i > 0; i--)
	{
		snake.xy[i].x = snake.xy[i - 1].x;
		snake.xy[i].y = snake.xy[i - 1].y;
	}
	//蛇头运动方向,根据方向标志来移动
	switch (snake.position)
	{
	case sup:
		snake.xy[0].y -= 10;
		break;
	case sdown:
		snake.xy[0].y += 10;
		break;
	case sright:
		snake.xy[0].x += 10;
		break;
	case sleft:
		snake.xy[0].x -= 10;
		break;
	case paus:
		_getch();
		break;
	}
	while (_kbhit())
	{
		char key = _getch();

		switch (key)
		{
		case up:
			//实现蛇的移动逻辑判断,不能往相反的方向移动
			if (snake.position != sdown)
				snake.position = sup;
			break;
		case down:
			if (snake.position != sup)
				snake.position = sdown;
			break;
		case left:
			if (snake.position != sright)
				snake.position = sleft;
			break;
		case right:
			if (snake.position != sleft)
				snake.position = sright;
			break;
		case 'p':
			system("pause");
			break;
		}
	}
	//判断蛇撞到自己时
	//当蛇头坐标等于蛇身时,撞到自己
	for (j = 2; j < snake.lenth; j++)
	{
		if (snake.xy[0].x == snake.xy[j].x && snake.xy[0].y == snake.xy[j].y)
			gameover2();
	}
}


//判断蛇是否撞墙
void HitWall()
{
	if (snake.xy[0].x > 490 || snake.xy[0].x < 100 || snake.xy[0].y > 590 || snake.xy[0].y < 100)
	{
		gameover();		//撞墙时,游戏结束
	}
}

//蛇吃食物功能
void EatFood()
{
	if (snake.xy[0].x == Food.foodxy.x && snake.xy[0].y == Food.foodxy.y)
	{
		snake.lenth++;
		Food.grade += 10;
		Food.symbol = 0;
	}
}


//初始化食物
void CreateFood()
{
	int i, x, y;
	x = rand() % 40 + 10;	//初始化食物坐标,要为10的倍数,否则无法对齐
	y = rand() % 50 + 10;
	Food.foodxy.x = x * 10;
	Food.foodxy.y = y * 10;
	Food.symbol = 1;

	//食物不与蛇身重叠
	for (i = 0; i < snake.lenth; i++)
	{
		if (Food.foodxy.x == snake.xy[i].x && Food.foodxy.y == snake.xy[i].y)
		{
			x = rand() % 40 + 10;	//重新生成一次食物
			y = rand() % 50 + 10;
			Food.foodxy.x = x * 10;
			Food.foodxy.y = y * 10;
		}
	}
}

//绘制食物
void drawfood()
{
	setfillcolor(GREEN);
	solidrectangle(Food.foodxy.x, Food.foodxy.y, Food.foodxy.x + 10, Food.foodxy.y + 10);
}

//显示分数

void grade()
{
	char player_grade[] = "当前分数";
	char grades[100];
	sprintf_s(grades, "%d", Food.grade);
	outtextxy(530, 100, player_grade);	//在右上角界面显示分数
	outtextxy(530, 275, "操作说明");
	outtextxy(530, 300, "使用wasd操作");
	outtextxy(530, 325, "w往上走，s往下走");
	outtextxy(530, 350, "a往左走，d往右走");
	outtextxy(530, 375, "p键暂停,按任意键继续");
	outtextxy(635, 100, grades);

}

void speedup()
{
	switch (Food.grade)
	{
	case 0: snake.speed = 120;
		outtextxy(50, 50, "你现在还只是一条小蛇，移动的很慢");
		break;
	case 10: snake.speed = 120;
		outtextxy(50, 50, "你现在还只是一条小蛇，移动的很慢");
		break;
	case 20: snake.speed = 120;
		outtextxy(50, 50, "你现在还只是一条小蛇，移动的很慢");
		break;
	case 30: snake.speed = 100;
		outtextxy(50, 50, "你的速度比以前快了，要小心哦");
		break;
	case 40: snake.speed = 100;
		outtextxy(50, 50, "你的速度比以前快了，要小心哦");
		break;
	case 50: snake.speed = 100;
		outtextxy(50, 50, "你的速度比以前快了，要小心哦");
		break;
	case 60: snake.speed = 85;
		outtextxy(50, 50, "速度又升级了，注意安全");
		break;
	case 70: snake.speed = 85;
		outtextxy(50, 50, "速度又升级了，注意安全");
		break;
	case 80: snake.speed = 70;
		outtextxy(50, 50, "速度越来越快了，我相信你可以的");
		break;
	case 90: snake.speed = 70;
		outtextxy(50, 50, "速度越来越快了，我相信你可以的");
		break;
	case 100:snake.speed = 60;
		outtextxy(50, 50, "速度更快了，小心别撞墙");
		break;
	case 110:snake.speed = 60;
		outtextxy(50, 50, "速度更快了，小心别撞墙");
		break;
	case 120:snake.speed = 55;
		outtextxy(50, 50, "速度似乎又快了些，你准备好了吗");
		break;
	case 130:snake.speed = 55;
		outtextxy(50, 50, "速度似乎又快了些，你准备好了吗");
		break;
	case 140:snake.speed = 50;
		outtextxy(50, 50, "看样子你还可以迎接更大的挑战，速度继续加快");
		break;
	case 150:snake.speed = 50;
		outtextxy(50, 50, "看样子你还可以迎接更大的挑战，速度继续加快");
		break;
	case 160:snake.speed = 50;
		outtextxy(50, 50, "看样子你还可以迎接更大的挑战，速度继续加快");
		break;
	default:snake.speed = 40;
		outtextxy(50, 50, "好吧，你厉害，我不加速度了，看你能走多远");
		break;
	}
}

//游戏结束
void gameover()
{
	settextstyle(25, 0, "楷体");
	outtextxy(530, 200, "怎么撞到墙了");
	outtextxy(530, 225, "下次注意");
	_getch();
	GameEnd();
}
void gameover2()
{

	settextstyle(25, 0, "楷体");
	outtextxy(530, 200, "这么饿吗");
	outtextxy(530, 225, "连自己的身体都不放过");
	outtextxy(530, 250, "好了，把自己咬死了");
	_getch();
	GameEnd();
}
//显示封面及设置字体
void topic()
{
	IMAGE back;
	mciSendString("open D:\\background.mp3 alias bkmusic", NULL, 0, NULL);
	mciSendString("play bkmusic repeat", NULL, 0, NULL);
	loadimage(&back, "D:\\background.jpg");
	putimage(0, 0, &back);

	
	outtextxy(200, 200, "按任意键开始游戏");
	outtextxy(200, 225, "祝您游戏愉快");
	_getch();
}

//游戏结束界面
void GameEnd()
{
	cleardevice();
	char choose1;
	char choose2[] = "您的下一步操作(继续游戏（y） || 退出游戏（n）)";
	settextcolor(COLORREF RGB(134, 235, 246));
	outtextxy(100, 175, choose2);
	outtextxy(100, 200, "或者尝试一下困难模式(g)");
	_getch();
	choose1 = _getch();
	switch (choose1)
	{
	case 'y': again();
	case 'n': exit(0);
	case 'g': difficult();
	default:exit(0);
	}
	_getch();
	exit(0);
}

void again()				//重新开始游戏
{
	snake.speed = 120;
	Food.grade = 0;
	setbkcolor(BLACK);
	cleardevice();
	createsnake();
	while (1)
	{
		gotoxy(0, 0);
		cleardevice();		//刷新蛇的路径
		CreateMap();
		grade();
		drawsnake();
		speedup();
		drawfood();
		SnakeMove();
		if (Food.symbol == 0)
		{
			CreateFood();
		}
		Sleep(snake.speed);
		HitWall();
		EatFood();
	}
	_getch();
}

void difficult()
{
	snake.speed = 30;
	Food.grade = 0;
	setbkcolor(BLACK);
	cleardevice();
	createsnake();
	while (1)
	{
		gotoxy(0, 0);
		cleardevice();		//刷新蛇的路径
		CreateMap();
		grade();
		drawsnake();
		drawfood();
		SnakeMove();
		speedup2();
		if (Food.symbol == 0)
		{
			CreateFood();
		}
		Sleep(snake.speed);
		HitWall();
		EatFood();
	}
	_getch();
}

void speedup2()
{
	switch (Food.grade)
	{
	case 0: snake.speed = 30;
		outtextxy(50, 50, "欢迎来到困难模式，这里的速度可是很快的哦");
		break;
	case 10: snake.speed = 30;
		outtextxy(50, 50, "欢迎来到困难模式，这里的速度可是很快的哦");
		break;
	case 20: snake.speed = 30;
		outtextxy(50, 50, "欢迎来到困难模式，这里的速度可是很快的哦");
		break;
	case 30: snake.speed = 28;
		outtextxy(50, 50, "欢迎来到困难模式，速度一直在加快哦");
		break;
	case 40: snake.speed = 28;
		outtextxy(50, 50, "欢迎来到困难模式，速度一直在加快哦");
		break;
	case 50: snake.speed = 28;
		outtextxy(50, 50, "欢迎来到困难模式，速度一直在加快哦");
		break;
	case 60: snake.speed = 28;
		outtextxy(50, 50, "欢迎来到困难模式，速度一直在加快哦");
		break;
	case 70: snake.speed = 26;
		outtextxy(50, 50, "欢迎来到困难模式，速度更快了");
		break;
	case 80: snake.speed = 26;
		outtextxy(50, 50, "欢迎来到困难模式，速度更快了");
		break;
	case 90: snake.speed = 24;
		outtextxy(50, 50, "欢迎来到困难模式，没错，速度还在加快哦");
		break;
	case 100:snake.speed = 24;
		outtextxy(50, 50, "欢迎来到困难模式，没错，速度还在加快哦");
		break;
	case 110:snake.speed = 24;
		outtextxy(50, 50, "欢迎来到困难模式，没错，速度还在加快哦");
		break;
	case 120:snake.speed = 24;
		outtextxy(50, 50, "欢迎来到困难模式，没错，速度还在加快哦");
		break;
	case 130:snake.speed = 22;
		outtextxy(50, 50, "欢迎来到困难模式，速度不会停下来");
		break;
	case 140:snake.speed = 22;
		outtextxy(50, 50, "欢迎来到困难模式，速度不会停下来");
		break;
	case 150:snake.speed = 22;
		outtextxy(50, 50, "欢迎来到困难模式，速度不会停下来");
		break;
	case 160:snake.speed = 22;
		outtextxy(50, 50, "欢迎来到困难模式，速度不会停下来");
		break;
	default:snake.speed = 20;
		outtextxy(50, 50, "欢迎来到困难模式，速度不会加快了，祝你好运");
		break;
	}
}